package com.zyg.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

//链接数据库
public class DBUtil {
	
	
	private static String user = "root";
	private static String password = "";
	private static String url = "jdbc:mysql://localhost:3306/apart?characterEncoding=utf-8";
	
	private static Connection connection;
	private static PreparedStatement statement;
	private static ResultSet rs;
	static { 
		try {
			/**
			 * 通过路劲动态加载Driver驱动
			 */
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	//定义getConnection返回数据库链接
	public static Connection getConnection() {
		
		try {
			connection = DriverManager.getConnection(url,user,password);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return connection;
	}
	
	//关闭链接
	public static void closeAll() throws SQLException {
		if (rs!= null) {
			rs.close();
		}
		if(statement != null) {
			statement.close();
		}
		if (connection != null) {
			connection.close();
		}
	}
	
	
	/**
	 * 封装基本的sql操作，查询以及其他操作
	 * 此处需要返回值ResultSet ,同时需要将sql作为参数，以及sql操作会传递参数需考虑
	 * @param sql 
	 * @throws SQLException 
	 */
	
	public static ResultSet select(String sql,Object[] obj) {
		connection = getConnection();
		try {
			statement = connection.prepareStatement(sql);
//			将传递过来的参数进行遍历，全部的放到prepareStatement对象中进行预处理
			for (int i = 0; i < obj.length; i++) {
				statement.setObject(i+1, obj[i]);
			}
			//参数预处理完毕后执行		
			rs = statement.executeQuery();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return rs;
		
	}
	/**
	 * 更新、添加、删除需要执行后的返回值判断是否执行成功
	 * @throws SQLException 
	 */
	public static int update(String sql,Object[] objects) {
		connection = getConnection();
		try {
			statement = connection.prepareStatement(sql);
			for (int i = 0; i < objects.length; i++) {
				statement.setObject(i+1, objects[i]);
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		int i = 0;
		try {
			i = statement.executeUpdate();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return i ;
	}
	//封装结果集，根据反射自动封装结果集到对应的javaBean中
	public static List<Object> ColumnToField(ResultSet rs,Class<?> clazz){
	 	//根据传递过来的类型，利用发射获取声明的属性，期中包含属性名以及属性的类型
        Field[] fields=clazz.getDeclaredFields();
        List<Object> list=new ArrayList<Object>();
        try {
			while(rs.next()){
				//利用反射实例化
				Object obj=clazz.newInstance();
			    for(Field f:fields){
			    	//遍历分别获取属性名以及属性的类型
			        String name=f.getName();
			        Class type=f.getType();
			        //利用反射里面的Method定义一个method用来承载类中或实例中的方法
			        Method method=null;
			        try {
			        	//clazz.getMethod获取声明的方法，因为要获取到set方法，此时将name中的第一个字母替换成大写
			            method=clazz.getMethod("set"+name.replaceFirst(name.substring(0, 1),
			                    name.substring(0, 1).toUpperCase()), type);       
			            //利用映射，调用此对象表示的底层方法并传递参数
			            method.invoke(obj,rs.getObject(name));
			        } catch (Exception e) {
			            e.printStackTrace();
			        }
			    }
			    list.add(obj);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
        return list;
    }
	
	
	
	
	
}
